package cn.keniykey.mc.viewlibrary.view.api.template;

import java.util.List;

import javax.annotation.Nullable;

import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;

import cn.keniykey.mc.viewlibrary.container.api.ContainerAnvil;
import cn.keniykey.mc.viewlibrary.container.api.ContainerAnvil.IContainerAnvilItemNameHandler;
import cn.keniykey.mc.viewlibrary.container.api.EContainerType;
import cn.keniykey.mc.viewlibrary.view.api.AbFrameView;
import cn.keniykey.mc.viewlibrary.view.api.FrameViewBundle;
import cn.keniykey.mc.viewlibrary.view.api.IViewClickHandler;
import cn.keniykey.mc.viewlibrary.view.api.ViewClickReport;
import cn.keniykey.mc.viewlibrary.view.api.template.ChooseViewIntentBuilder.EChooseMenuViewIntentKey;
import cn.keniykey.mc.viewlibrary.view.api.template.InputViewIntentBuilder.EInputMenuViewCustomDisplay;
import cn.keniykey.mc.viewlibrary.view.api.template.InputViewIntentBuilder.EInputMenuViewIntentKey;

public abstract class AbInputView extends AbFrameView{
	public enum EInputResult{
		CONFIRM,CANCEL,UNKNOWN;
		
		public static EInputResult muchResult(int result) {
			switch(result) {
			case 1: return CONFIRM;
			case 2: return CANCEL;
			default:
			}
			return UNKNOWN;
		}
		public boolean isConfirm() {
			return this.equals(CONFIRM);
		}
	}
	public enum EInputResultIntentKey {
		INPUT,FORWARD;
	}
	
	private InputViewCountdownRunnable runnable;
	private boolean lock = true;

	protected AbInputView(Plugin plugin1, Player player1) {
		super(plugin1, player1);
	}
	
	@Override
	protected void onCreateForResult(int requestcode) {
		super.onCreateForResult(requestcode);
		this.setViewType(EContainerType.ANVIL);
		int countdown = 0;
		ItemStack item_input = null,item_confirm = null,item_countdown = null;
		if(this.getIntent().hasExtras()) {
			final FrameViewBundle bundle = this.getIntent().getExtras();
			this.setTitle((bundle.hasValue(EChooseMenuViewIntentKey.CUSTOM_TITLE.toString()) ? 
					bundle.getString(EChooseMenuViewIntentKey.CUSTOM_TITLE.toString(), "input") : this.onDefaultTitle()));
			if(bundle.hasValue(EInputMenuViewIntentKey.CUSTOMDISPLAY.toString())) {
				final EInputMenuViewCustomDisplay mode = (EInputMenuViewCustomDisplay) bundle.getValue(EInputMenuViewIntentKey.COUNTDOWN.toString(), EInputMenuViewCustomDisplay.MATERIAL);;
				if(EInputMenuViewCustomDisplay.FULLY.equals(mode)) {
					item_input = bundle.getValue(EInputMenuViewIntentKey.CUSTOMDISPLAY_INPUT.toString(), null);
					if((countdown = this.readyCountdown(bundle)) > 0) {
						item_countdown = bundle.getValue(EInputMenuViewIntentKey.CUSTOMDISPLAY_COUNTDOWN.toString(), null);
					}
					item_confirm = bundle.getValue(EInputMenuViewIntentKey.CUSTOMDISPLAY_CONFIRM.toString(), null);
				}else {
					item_confirm = this.onDeafultIconOfConfirm(bundle.getValue(EInputMenuViewIntentKey.CUSTOMDISPLAY_CONFIRM.toString(), null));
					if((countdown = this.readyCountdown(bundle)) > 0) item_countdown = this.onDeafultIconOfCountdown(bundle.getValue(EInputMenuViewIntentKey.CUSTOMDISPLAY_COUNTDOWN.toString(), null));
					final String name = bundle.getValue(EInputMenuViewIntentKey.CUSTOM_INPUT_NAME.toString(), "@");
					final List<String> lore = bundle.getValue(EInputMenuViewIntentKey.CUSTOM_INPUT_LORE.toString(), null);
					item_input = this.onDeafultIconOfInput(bundle.getValue(EInputMenuViewIntentKey.CUSTOMDISPLAY_INPUT.toString(), null), name, lore);
				}
			}else {
				countdown = this.readyCountdown(bundle);
			}
		}
		if(item_input == null) item_input = this.onDeafultIconOfInput(null, "@", null);
		this.setIcon(0, item_input);
		if(this.runnable != null) {
			if(item_countdown == null) item_countdown = this.onDeafultIconOfCountdown(null);
			item_countdown.setAmount(countdown);
			this.runnable.item_countdown1 = item_countdown;
			this.setIcon(1, item_countdown);
		}
		this.setIconClick(2, null, new IViewClickHandler() {
			@Override
			public void onClick(Player player,AbFrameView view, ViewClickReport report) {
				if(report.getCursorItemStack() == null || AbInputView.this.lock) return;
				if(AbInputView.this.runnable != null) AbInputView.this.runnable.cancel();
				final FrameViewBundle bundle = new FrameViewBundle();
				bundle.putValue(EInputResultIntentKey.INPUT.toString(), report.getCursorItemStack().getItemMeta().getDisplayName());
				AbInputView.this.setResultAndIntent(1, bundle);
				view.finish();
			}
		});
		if(item_confirm == null) item_confirm = this.onDeafultIconOfConfirm(null);
		((ContainerAnvil)this.getContainer()).setContainerAnvilItemNameHandler(new InputViewAnvilItemName(item_confirm, item_input.getItemMeta().getDisplayName()));
	}
	private final class InputViewAnvilItemName implements IContainerAnvilItemNameHandler{
		private final ItemStack item_confirm1;
		private final ItemMeta item_confirm1_meta;
		private final String default_name1;
		InputViewAnvilItemName(ItemStack item_confirm,String default_name) {
			this.item_confirm1 = item_confirm;
			this.item_confirm1_meta = item_confirm.getItemMeta();
			this.default_name1 = default_name;
		}
		@Override
		public void onAnvilItemNameResponse(Player player, ContainerAnvil anvil, String str) {
			if(this.default_name1.equals(str)) {
				final ItemStack item = anvil.getItemStack(2);
				if(item == null) return;
				AbInputView.this.setIcon(2, null);
				AbInputView.this.lock = true;
				AbInputView.this.useEmptyRefresh(0);
				return;
			}
			AbInputView.this.lock = false;
			this.item_confirm1_meta.setDisplayName(str);
			this.item_confirm1.setItemMeta(this.item_confirm1_meta);
			if(anvil.getItemStack(2) == null) {
				AbInputView.this.setIcon(2, this.item_confirm1);
			}else {
				AbInputView.this.refreshIcon(2);
			}
		}
	}
	private int readyCountdown(final FrameViewBundle bundle) {
		if(bundle.hasValue(EInputMenuViewIntentKey.COUNTDOWN.toString())) {
			final int countdown = bundle.getInt(EInputMenuViewIntentKey.COUNTDOWN.toString(), 0);
			if(countdown > 127) throw new RuntimeException("The set time should not be less than 1 or greater than 127(设置的时间不应小于1或大于127)");
			if(countdown > 0) this.runnable = new InputViewCountdownRunnable();
			return countdown;
		}
		return 0;
	}
	private final class InputViewCountdownRunnable extends BukkitRunnable{
		private ItemStack item_countdown1;
		@Override
		public void run() {
			final int second = (this.item_countdown1.getAmount()-1);
			if(second > 0) {
				this.item_countdown1.setAmount(second);
				AbInputView.this.refreshIcon(1);
				if(AbInputView.this.getContainer().getItemStack(2) != null) AbInputView.this.refreshIcon(2);
				return;
			}
			AbInputView.this.finish();
		}
		
	}
	@Override
	protected void onShow() {
		super.onShow();
		if(this.runnable != null) this.runnable.runTaskTimerAsynchronously(this.getPlugin(), 20l, 20l);
	}
	@Override
	protected void onHidden() {
		super.onHidden();
		if(this.runnable == null || this.runnable.isCancelled()) return;
		this.runnable.cancel();
		this.setResultAndIntent(2, null);
	}
	private void setResultAndIntent(int resultcode,@Nullable FrameViewBundle bundle) {
		if(this.getIntent().hasExtras()) {
			final FrameViewBundle extras = this.getIntent().getExtras();
			if(extras.hasValue(EInputMenuViewIntentKey.FORWARD_CONTENT.toString())) {
				if(bundle == null) bundle = new FrameViewBundle();
				bundle.putValue(EInputResultIntentKey.FORWARD.toString(), extras.getValue(EInputMenuViewIntentKey.FORWARD_CONTENT.toString(), null));
			}
		}
		this.setResult(resultcode, bundle);
	}
	@Deprecated
	@Override
	public void hidden() {
	}
	
	protected String onDefaultTitle() {
		return "InputView";
	}
	protected final void useEmptyRefresh(int slot) {
		final ItemStack item = this.getContainer().getItemStack(slot);
		this.setIcon(0, null);
		Bukkit.getScheduler().runTaskAsynchronously(this.getPlugin(), ()->{
			this.setIcon(0, item);
		});
	}
	protected abstract ItemStack onDeafultIconOfConfirm(@Nullable Material type);
	protected abstract ItemStack onDeafultIconOfCountdown(@Nullable Material type); //可以试着使用附魔书
	protected abstract ItemStack onDeafultIconOfInput(@Nullable Material type,String name,@Nullable List<String> lore);
}